/************************************************************
 *	ProjectName:   LT2911R
 *	FileName:	   LT2911R_LVDS_TO_MIPI.c
 *	BuildData:	   2020-05-19
 *	Version��      V8.0
 * 	Author:        xhguo
 * 	Company:	   Lontium
 ************************************************************/

/*
V8.0 20200519

*/

//#include	"include.h"

//#ifdef _lvds_to_mipi_
/////////////////User configure Options Start////////////////////////////
// panel_video timing is expected output timing.
// this timing is used to generate test pattern, and varify if lvds video is stable.

// hfp, hs, hbp,hact,htotal,vfp, vs, vbp, vact,vtotal, pclk_khz

#include "lt2911r_lvds_to_mipi.h"
#include "i2c.h"
#include "lt2911.h"
#include "lt2911r_common.h"
#include "lt2911r_input_lvds.h"
#include "lt2911r_output_mipi.h"
#include "printf.h"

// const struct video_timing panel_video =  {120, 29, 59, 800, 1008, 20, 20, 8, 1280, 1328, 80000};
struct video_timing panel_video = {16, 16, 5, 800, 845, 16, 16, 20, 1280, 1340, 68000};
// GCM_video timing is expected input timing.
// struct video_timing GCM_video = {120, 29, 59, 800, 1008, 20, 20, 8, 1280, 1328, 80000};
struct video_timing GCM_video = {16, 16, 20, 1280, 1340, 16, 16, 5, 800, 845, 68000};
/////////////////User configure Options End////////////////////////////

////////////////////////////////////////////////////////////////////////////////////
struct video_timing Input_video = {0, 0, 0, 0, 0, 0, 0, 0};
struct video_timing Output_video = {0, 0, 0, 0, 0, 0, 0, 0};

// static bool lt2911r_cfg_done = 0;
// static bool lt2911r_lvds_video_stable = 0;
// static bool lt2911r_lvds_clock_stable = 0;
// static bool lt2911r_lvds_pll_locked_flag = 0;

void LT2911R_LowPowerInit_L2M(void)
{
	// disable unused function
	HDMI_WriteI2C_Byte(0xff, 0x81);
	HDMI_WriteI2C_Byte(0x0a, 0xc0); // 20190302
	HDMI_WriteI2C_Byte(0x0b, 0x00);
	HDMI_WriteI2C_Byte(0x0c, 0x1b);
	HDMI_WriteI2C_Byte(0x0d, 0x10);
	HDMI_WriteI2C_Byte(0x0f, 0x81);
	HDMI_WriteI2C_Byte(0x10, 0xf8);
	HDMI_WriteI2C_Byte(0x1f, 0x0b);
	HDMI_WriteI2C_Byte(0x31, 0x00); // 20190302
	HDMI_WriteI2C_Byte(0x32, 0x00);
	HDMI_WriteI2C_Byte(0x34, 0xd0);
	HDMI_WriteI2C_Byte(0x35, 0x00);
	HDMI_WriteI2C_Byte(0x36, 0x00);
	HDMI_WriteI2C_Byte(0x37, 0x00);
	// MLTX diable portA and B
	HDMI_WriteI2C_Byte(0x3a, 0x30); // M
	HDMI_WriteI2C_Byte(0x41, 0x00);
	HDMI_WriteI2C_Byte(0x42, 0xfc);

	HDMI_WriteI2C_Byte(0xff, 0x82);
	HDMI_WriteI2C_Byte(0x5c, 0xaa);
	HDMI_WriteI2C_Byte(0x5d, 0x80);
	HDMI_WriteI2C_Byte(0x08, 0x00);
	HDMI_WriteI2C_Byte(0x10, 0x01); // 0x04
	HDMI_WriteI2C_Byte(0x18, 0x00);
	HDMI_WriteI2C_Byte(0x19, 0x00);
	HDMI_WriteI2C_Byte(0x1a, 0x00);
	HDMI_WriteI2C_Byte(0x1b, 0x00);
	HDMI_WriteI2C_Byte(0x1c, 0x00);
	HDMI_WriteI2C_Byte(0x1d, 0x02);
	HDMI_WriteI2C_Byte(0x43, 0x80);
	HDMI_WriteI2C_Byte(0x44, 0x00);
	HDMI_WriteI2C_Byte(0x45, 0x00);
	HDMI_WriteI2C_Byte(0x4d, 0x00);
	HDMI_WriteI2C_Byte(0x4e, 0x00);
	HDMI_WriteI2C_Byte(0x4f, 0x00);
}

void LT2911R_RxTxSlection_L2M(void)
{
	HDMI_WriteI2C_Byte(0xff, 0x85);
	HDMI_WriteI2C_Byte(0x88, 0x10);
}

void LT2911R_Patten_debug_L2M(void)
{
	LT2911R_ChipID();
	LT2911R_SystemInit();
	LT2911R_DdrInit();

	LT2911R_Patten(&panel_video);
	LT2911R_MipiTxPllAuto();
	LT2911R_MipiTxPhy(); // lp 11

	LT2911R_MipiTxDigital(&panel_video);
	LT2911R_VpReset();

	Panel_Display(1);
	Timer0_Delay1ms(100);
	while (1)
		;
}

void LT2911R_Init()
{
	u8 i;
	LT2911R_ChipID();
	LT2911R_SystemInit();

	LT2911R_RxTxSlection_L2M();

	LT2911R_DdrInit();

	LT2911R_LvdsRxPhy();
	LT2911R_LvdsRxPll();
	LT2911R_LvdsRxDigital(&GCM_video);

	LT2911R_DesscPll_lvds();
	LT2911R_VpPro(&panel_video);

	LT2911R_MipiTxPllAuto();
	LT2911R_MipiTxPhy(); // lp 11

	LT2911R_LvdsRxClkCheck_Debug();
	LT2911R_MipiTxClkCheck_Debug();

	for (i = 0; i < 10; i++) {
		printf("\r\n LT2911R_Init: lvds clk check: i = %02x", i);
		if (LT2911R_LvdsClockChecked()) //  lvds clk checked
		{
			continue;
		} else {
			break;
		}
	}

	for (i = 0; i < 10; i++) {
		printf("\r\n LT2911R_Init: lvds pll check: i = %02x", i);
		if (LT2911R_LvdsPllChecked()) // LvdsPllChecked
		{
			LT2911R_LvdsRxPll();
		} else {
			break;
		}
	}

	for (i = 0; i < 5; i++) {
		printf("\r\n LT2911R_Init: vp input video stable check: i = %02x", i);
		if (LT2911R_VpInputVideoStable(&GCM_video)) // video stable==0
		{
			LT2911R_AutoVideoCfg(&Input_video, &panel_video, &Output_video);
			LT2911R_CscCfg(&Input_video, RGB, RGB);
			LT2911R_Retimer(&Output_video);
			LT2911R_MipiTxDigital(&Output_video);
			LT2911R_VpReset();
			break;
		}
	}

	for (i = 0; i < 5; i++) {
		printf("\r\n LT2911R_Init: vp input video stable check: i = %02x", i);
		if (LT2911R_VpOutputVideoStable(&Output_video)) {

			Panel_Display(1);
			LT2911R_InterruptEnable(RXPLL_CLK_UNSTB, 1);
			LT2911R_InterruptEnable(VID_CHK_CHG, 1);
			LT2911R_InterruptEnable(DDR_FIFO_ERROR, 1);
			break;
		} else {
			LT2911R_VpReset();
			Timer0_Delay1ms(100);
		}
	}
	printf("\r\n init done!!");
}
void LT2911R_MainLoop(void)
{
	static int lt2911r_cfg_done = 1;
	static int lt2911r_lvds_video_stable = 1;
	static int lt2911r_lvds_clock_stable = 1;

	Timer0_Delay1ms(1000);
	LT2911R_PiAuto();

	if (LT2911R_LvdsClockChecked()) // mainloop check1: lvds rxpll locked or not
	{
		lt2911r_cfg_done = 0;
		lt2911r_lvds_video_stable = 0;
		lt2911r_lvds_clock_stable = 0;
	} else {
		lt2911r_lvds_clock_stable = 1;
	}

	if (lt2911r_lvds_clock_stable) {
		if (LT2911R_LvdsPllChecked()) // mainloop check1: lvds rxpll locked or not
		{
			LT2911R_LvdsRxPll();
			lt2911r_cfg_done = 0;
			lt2911r_lvds_video_stable = 0;
		}
	}

	if (lt2911r_lvds_video_stable) {
		if (LT2911R_LvdsChgChecked()) // mainloop check2: check lvds clock and lvds video if changed
		{
			lt2911r_cfg_done = 0;
			lt2911r_lvds_video_stable = 0;
		}
	}

	if (lt2911r_cfg_done) // mainloop check2: config done, ddr tx/rx fifo
	{
		if (LT2911R_DdrFifoStatusChecked()) {
			lt2911r_cfg_done = 0;
			lt2911r_lvds_video_stable = 0;
		}
	}
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
	if (!lt2911r_cfg_done) // disable panel dispaly.
	{
		Panel_Display(0);
	}
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
	if (lt2911r_lvds_clock_stable) {
		if (!lt2911r_cfg_done) {
			if (!lt2911r_lvds_video_stable) {
				if (LT2911R_VpInputVideoStable(&GCM_video)) // video stable
				{
					LT2911R_AutoVideoCfg(&Input_video, (struct video_timing *)&panel_video, &Output_video);
					LT2911R_CscCfg(&Input_video, RGB, RGB);
					LT2911R_Retimer(&Output_video);
					LT2911R_MipiTxDigital(&Output_video);
					LT2911R_DdrInit();
					LT2911R_VpReset();
					LT2911R_InterruptEnable(RXPLL_CLK_UNSTB, 1);
					LT2911R_InterruptEnable(VID_CHK_CHG, 1);
					lt2911r_lvds_video_stable = 1;
				} else {
					lt2911r_lvds_video_stable = 0;
				}
			} else {
				if (LT2911R_VpOutputVideoStable(&Output_video)) {
					lt2911r_cfg_done = 1;
					Panel_Display(1);
					LT2911R_InterruptEnable(DDR_FIFO_ERROR, 1);
					printf("\r\n LT2911R Cfg Done!!");
					// while(1);
				} else {
					LT2911R_DdrInit();
					LT2911R_VpReset();
				}
			}
		}
	}
}

void LT2911R_Config_lvds_to_mipi(void)
{
#if VIDEO_PATTERN
	printf("\r\n LT2911R_Patten_debug_mipi");
	LT2911R_Patten_debug_L2M();
#else
	LT2911R_Init();
	while (1) {
		LT2911R_MainLoop();
		Timer0_Delay1ms(1000);
	}
#endif
}

//#endif
